package com.zz.server.handle.defaults;

import com.zz.common.annotation.Executor;
import com.zz.common.config.Constants;
import com.zz.common.datasource.DataSource;
import com.zz.common.datasource.DataSourceFactory;
import com.zz.common.entity.*;
import com.zz.common.enums.MessageType;
import com.zz.common.enums.SerializationType;
import com.zz.common.handle.executor.AbstractMessageExecutor;
import com.zz.common.protocol.DefaultProtocol;
import com.zz.common.utils.ObjectUtil;
import com.zz.common.utils.JsonUtil;
import com.zz.common.utils.SnowflakeUtil;
import com.zz.server.config.ChannelCache;
import io.netty.channel.ChannelHandlerContext;
import lombok.extern.slf4j.Slf4j;

import java.nio.charset.StandardCharsets;
import java.util.List;
import java.util.concurrent.ConcurrentHashMap;
import java.util.stream.Collectors;

/**
 * 授权认证处理
 */
@Slf4j
@Executor(msgType = MessageType.C_TYPE_AUTH)
public class AuthExecutor extends AbstractMessageExecutor {

    private static final DataSource dataSource = DataSourceFactory.getTunnelSource();

    @Override
    public void execute(Information information) {
        ChannelHandlerContext context = information.getContext();
        String header = information.getProtocolMsg().getHeader();

        try {
            if (isEmpty(header)) {
                sendAndReturnError(context, "HEADER IS NULL");
            }

            Header headerInfo = JsonUtil.toObjectByJson(header);
            if (isEmpty(headerInfo.getClientId()) || isEmpty(headerInfo.getClientKey())) {
                sendAndReturnError(context, "HEADER.CLIENT_ID AND HEADER.CLIENT_KEY IS NULL");
            }

            UserClient client = dataSource.getUserClientById(headerInfo.getClientId());
            if (!headerInfo.getClientKey().equals(client.getClientKey())) {
                sendAndReturnError(context, "CLIENT_KEY ERROR...");
            }

            sendAuthMessage(context, Constants.Strings.SUCCESS, Constants.Strings.EMPTY_STR);
            List<String> domains = getClientDomains(client.getClientId());

            // 添加域名映射
            ChannelCache.addDomainChannelCache(domains, context.channel());
            context.channel().attr(Constants.Attributes.CHANNEL_CACHE).set(new ConcurrentHashMap<>());
        } catch (Exception e) {
            log.error("授权认证处理异常", e);
            sendAuthMessage(context, Constants.Strings.FAIL, "AUTH ERROR...");
        }

    }


    private boolean isEmpty(String str) {
        return ObjectUtil.isEmpty(str);
    }

    private void sendAndReturnError(ChannelHandlerContext context, String message) {
        sendAuthMessage(context, Constants.Strings.FAIL, message);
        return;
    }

    private List<String> getClientDomains(String clientId) {
        return dataSource.getClientConfig(clientId)
                .stream()
                .map(ClientConfig::getDomain)
                .collect(Collectors.toList());
    }

    /**
     * 发送消息
     * @param context
     * @param status
     * @param body
     */
    private void sendAuthMessage(ChannelHandlerContext context, String status, String body) {
        DefaultProtocol protocol = DefaultProtocol.builder().type(MessageType.C_TYPE_AUTH).serialNumber(SnowflakeUtil.genSnowflakeId())
                        .header(status).data(body.getBytes(StandardCharsets.UTF_8)).serializationType(SerializationType.PROTOSTUFF).build();
        context.writeAndFlush(protocol).addListener(future -> {
            if (future.isSuccess()) {
                ObjectUtil.closeContext(context, status);
            }
        });
    }





}
